package il.ac.braude.sona.ocsf.client;

import il.ac.braude.sona.constants.Mssg;
import il.ac.braude.sona.constants.Resources;
import il.ac.braude.sona.control.LoginController;

import java.awt.Cursor;
import java.awt.Font;
import java.awt.FontFormatException;
import java.awt.Window;
import java.io.File;
import java.io.IOException;
import java.io.PrintStream;
import java.net.URL;
import java.sql.SQLException;
import java.util.Enumeration;
import java.util.HashMap;

import javax.swing.JOptionPane;
import javax.swing.UIManager;
/**
 * 
 * Class for representing a client, opens a connection to server
 * all the controllers in the project use this class instance to connect to the server 
 * sends messages and receives messages from server
 * @author Ofek Ron
 * @author Avihay Avitan
 * @author Nitzan Inbar
 * @author Sasha Rozenthal
 */
public class Client extends AbstractClient {
	/**
	 * save the response listener who waits for an answer from the server
	 */
	private HashMap<Long,ServerResponseListener> responseAwaiting = new HashMap<Long,ServerResponseListener>();
	/**
	 * for saving the type of the listeners
	 */
	private HashMap<String,ServerResponseListener> typeListeners = new HashMap<String,ServerResponseListener>();
	private int i;
	/**
	 * static instance for server connection
	 */
	private static Client instance;
	/**
	 * initialize a new Client
	 * @param host  - the machine's host
	 * @param port  - port of the server
	 */
	private Client(String host, int port) {
		super(host, port);
	}
	@Override
	protected void handleMessageFromServer(Object msg) {
		Mssg mssg = (Mssg)msg;
		ServerResponseListener listener = responseAwaiting.get(mssg.getID());
		if (listener==null) listener=typeListeners.get(mssg.getType());
		else responseAwaiting.remove(mssg.getID());
		if (listener==null) return;
		freeWaiting();
		listener.onServerResponse(mssg);
	}
	
	/**
	 * set curser waiting when waiting for server answer
	 */
	private void setWaiting() {
		for (Window f : Window.getWindows()) 
			f.setCursor(Cursor.getPredefinedCursor(Cursor.WAIT_CURSOR));
	}
	/**
	 * set curser default when waiting for server answer
	 */
	private void freeWaiting() {
		for (Window f : Window.getWindows()) 
			f.setCursor(Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
	}
	
	/**
	 * sends a message to the server
	 * @param listener - the listener that is waiting for an answer
	 * @param mssg    - the message to be sent,contains String for identification and may contain objects as values
	 * @throws IOException
	 */
	public void sendToServer(ServerResponseListener listener,Mssg mssg) throws IOException {
		setWaiting();
		responseAwaiting.put(mssg.getID(), listener);
		sendToServer(mssg);
	}
	/**
	 * @return static instance of client
	 */
	public static Client getInstance() {
		return instance;
	}
	/**
	 * saves the listeners by types of messages
	 * @param typeOfMssg  - message type
	 * @param listener   - the listener that is waiting for an answer
	 */
	public void registerMssgListenerByType(String typeOfMssg,ServerResponseListener listener) {
		typeListeners.put(typeOfMssg, listener);
	}
	/**
	 * initialize the instance parameter, open a new connection to the server
	 * @param host - the machine's host
	 * @param port  - the server port
	 * @throws IOException
	 */
	public static void connect(String host, int port) throws IOException {
		instance=new Client(host, port); 
		instance.openConnection();
	}
	public static void initiateClient() throws IOException{
		new File("C:\\sona").mkdirs();
		new File("C:\\sona\\clientlogOut.txt").createNewFile();
		PrintStream p = new PrintStream(new File("C:\\sona\\clientlogOut.txt"));
		System.setErr(p);
		//System.setOut(p);
		try {
			URL imgURL = ClassLoader.getSystemResource("optima.ttf");
			Font font = Font.createFont(Font.TRUETYPE_FONT,imgURL.openStream());
			Resources.applicationFont = font.deriveFont(Font.BOLD,16);
			imgURL = ClassLoader.getSystemResource("futura.ttf");
			font = Font.createFont(Font.TRUETYPE_FONT,imgURL.openStream());
			Resources.Futura18= font.deriveFont(Font.PLAIN,18);
			Resources.Futura20= font.deriveFont(Font.PLAIN,20);
			Enumeration<Object> keys = UIManager.getDefaults().keys();
			while (keys.hasMoreElements()) {
				Object key = keys.nextElement();
				Object value = UIManager.get(key);
				if (value instanceof javax.swing.plaf.FontUIResource)
					UIManager.put(key, Resources.applicationFont);}
			} catch (FontFormatException e1) {
				e1.printStackTrace();
			}
	}
	/**
	 * the main method of the project, initialize fonts and images we will use throughout the program
	 * tries to open a new connection via user input of server ip
	 * and if connection is valid initialize the login gui frame and waits for user input 
	 * @param args
	 * @throws InterruptedException
	 * @throws SQLException
	 * @throws IOException
	 */
	public static void main(String[] args) throws InterruptedException, SQLException, IOException {
		initiateClient();
		makeConection();
		startLoginSession();
	}
	public static void startLoginSession() {
		LoginController loginController =  new LoginController();
		loginController.execLogin();
	}
	private static void makeConection() {
		try {
			Client.connect(JOptionPane.showInputDialog("please enter server ip"),12389);
		} catch (IOException e) {
			JOptionPane.showMessageDialog(null, "fatal : couldnt reach server");
			return;
		}		
	}

}
